/**
 * Copyright (c) 2013 onionframework.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.onionframework.code;

import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.Type;
import org.hibernate.proxy.HibernateProxyHelper;
import org.onionframework.code.model.Code;
import org.onionframework.code.model.CodeType;
import org.onionframework.code.service.CodeService;
import org.onionframework.code.service.CodeTypeService;
import org.onionframework.core.util.Exceptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author allan
 *
 */
@Component("code.tools")
public class CodeToolsImpl implements CodeTools {

	@Autowired private CodeService codeService;
	@Autowired private CodeTypeService codeTypeService;
	
	@Autowired private SessionFactory sessionFactory;
	
	@Override
	public Code getCode(String value, String type) {
		return this.codeService.getCode(value, this.codeTypeService.getCodeType(type));
	}

	@Override
	public List<Code> getCodeList(String type) {
		return this.codeService.getCodeList(this.codeTypeService.getCodeType(type));
	}

	@Override
	public Code getCode(Object object, String property, String value) {
		return this.getCode(value, this.getCodeType(object, property));
	}

	@Override
	public void setCode(Object object, String property, String value) {
		try {
			PropertyUtils.setProperty(object, property, this.getCode(object, property, value));
		} catch (Exception e) {
			throw Exceptions.system("设置代码属性异常：" + object.getClass().getName() + "." + property, e);
		}
	}
	
	protected CodeType getCodeType(Object object, String property){
		Class<?> entityClass = this.sessionFactory.getClassMetadata(HibernateProxyHelper.getClassWithoutInitializingProxy(object)).getMappedClass();
		CodeType codeType = null;
		try {
			Type type = PropertyUtils.getPropertyDescriptor(entityClass.newInstance(), property).getReadMethod().getAnnotation(Type.class);
			codeType = this.codeTypeService.getCodeType(type.parameters()[0].value());
		} catch (Exception e) {
			throw Exceptions.system("无法获取对象的代码类型：" + entityClass.getName() + "." + property, e);
		}
		
		if(codeType != null)
			return codeType;
		else
			throw Exceptions.system("无法获取对象的代码类型：" + entityClass.getName() + "." + property, null);
	}

	/* (non-Javadoc)
	 * @see org.onionframework.code.CodeTools#getCode(java.lang.String, org.onionframework.code.model.CodeType)
	 */
	@Override
	public Code getCode(String value, CodeType type) {
		return this.codeService.getCode(value, type);
	}

}
